unit uMainFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,

  GlScene, GlObjects, GlCadencer, GLWin32Viewer, GLRenderContextInfo, GlWindowsFont, GlHudObjects,
  GlMaterial,
  VectorGeometry,
  uTweener,
  uRadiualGroup,
  uSimpleAnimationsObjects,
  uGlSceneProfiler;

const
  EarthMats: array [1..5] of String = ('aside', 'audio', 'chat', 'default', 'gallery');
  PlanetMats: array [1..3] of String = ('planet_1', 'planet_2', 'planet_3');
type

  TGroupPlanet = record
    fPlanet: TPlanetButton;
    fGroup: TRadialGroup;
  end;

  TfrmMain = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    {Main Objects}
    fGlScene: TGlScene;
    fCadencer: TGLCadencer;
    fViewer: TGLSceneViewer;
    fCamera: TGlCamera;
    fMainDummy: TGlDummyCube;
    fFpsTimer: Single;
    fMatLib: TGlMaterialLibrary;

    {Text Objects}
    fWinFont: TGLWindowsBitmapFont;
    fHudText: TGLHUDText;
    fBack: TGlHudSprite;

    //fGroup: TRadialGroup;
    fPlanets: array [1..3] of TGroupPlanet;
    fClickedText: TGLHUDText;

    {Tween-objects}
    fTweener: TTweener;

    MousePressed: Boolean;
  protected
    function GetGroupByPlanet(aPlanet: TGlHudSprite): TGroupPlanet;
    function GetGroupByRadialMenu(aRadialMenu: TGlHudSprite): TGroupPlanet;
    procedure OnPlanetOut(aSelf: TGlHudSprite);
    procedure OnPlanetOver(aSelf: TGlHudSprite);
    procedure OnItemMouseClick(aSelf: TRadialGroup; aItem: TRadialElement; aItemIndex: Integer);
  public
    Procedure InitFontAndSprites;
    Procedure InitMaterials;
    Procedure InitTweener;
    Procedure OnCadencerProgress(Sender : TObject; const deltaTime, newTime : Double);
  end;

var
  frmMain: TfrmMain;

implementation
uses
  glKeyboard,
  GLCrossPlatform,
  gltexture,
  uDemoInit;
{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  fFpsTimer := 0;
  CreateDemo(self, fGlScene, fCadencer, fViewer);
  
  fCamera := TGlCamera.CreateAsChild(fGlScene.Objects);
  with fCamera do
  begin
    Position.SetPoint(0, 0, 5);
    Direction.SetVector(0, 0, -1);
    Up.SetVector(0, 1, 0);
    CameraStyle := csOrthogonal;
    SceneScale := 0.1;
  end;

  fMainDummy := TGLDummyCube.CreateAsChild(fGlScene.Objects);
  fMainDummy.ObjectsSorting := osNone;

  fViewer.Camera := fCamera;
  fCadencer.OnProgress := OnCadencerProgress;

  fMatLib := TGlMaterialLibrary.Create(self);

  InitMaterials;
  InitFontAndSprites;
  InitTweener;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  FreeAndNil(fTweener);
end;

function TfrmMain.GetGroupByPlanet(aPlanet: TGlHudSprite): TGroupPlanet;
var
  i: integer;
begin
  for i := 1 to 3 do
    if fPlanets[i].fPlanet = aPlanet then
      result := fPlanets[i];
end;

function TfrmMain.GetGroupByRadialMenu(aRadialMenu: TGlHudSprite): TGroupPlanet;
var
  i: integer;
begin
  for i := 1 to 3 do
    if fPlanets[i].fGroup = aRadialMenu then
      result := fPlanets[i];
end;

procedure TfrmMain.OnPlanetOut(aSelf: TGlHudSprite);
begin
  GetGroupByPlanet(aSelf).fGroup.Hide;
end;

procedure TfrmMain.OnPlanetOver(aSelf: TGlHudSprite);
begin
  GetGroupByPlanet(aSelf).fGroup.Show;
end;

procedure TfrmMain.OnItemMouseClick(aSelf: TRadialGroup; aItem: TRadialElement; aItemIndex: Integer);
begin
  with GetGroupByRadialMenu(aSelf).fPlanet.Material do
    fClickedText.Text := 'Clicked: ' + LibMaterialName + ', Item - ' + inttostr(aItemIndex);
end;

procedure TfrmMain.FormActivate(Sender: TObject);
begin
  fCadencer.Enabled := true;
end;

Procedure TfrmMain.InitFontAndSprites;
var
  i: integer;
begin
  fWinFont := TGLWindowsBitmapFont.Create(self);
  fWinFont.Font.Name := 'Arial';

  fBack := TGlHudSprite.CreateAsChild(fMainDummy);
  with fBack do
  begin
    Material.LibMaterialName := 'back_1';
    Material.MaterialLibrary := fMatLib;
    Width := Material.GetActualPrimaryTexture.Image.Width;
    Height := Material.GetActualPrimaryTexture.Image.Height;
    Position.SetPoint(Width / 2, Height / 2, 0);
  end;

  fHudText := TGLHUDText.CreateAsChild(fMainDummy);
  with fHudText do
  begin
    BitmapFont := fWinFont;
    Text := 'Lampogolovii presents ''RadialGroup Demo''';
    ModulateColor.SetColor(1, 1, 1, 0.7);
    Position.SetPoint(5, 385, 0);
    Alignment := taLeftJustify;
  end;

  fClickedText := TGLHUDText.CreateAsChild(fMainDummy);
  with fClickedText do
  begin
    BitmapFont := fWinFont;
    Text := '';
    ModulateColor.SetColor(1, 1, 1, 0.7);
    Position.SetPoint(590, 2, 0);
    Alignment := taRightJustify;
  end;

  for i := 1 to 3 do
    with fPlanets[i] do
    begin
      fPlanet := TPlanetButton.CreateAsChild(fMainDummy);
      with fPlanet do
      begin
        Material.LibMaterialName := 'planet_' + inttostr(i);
        Material.MaterialLibrary := fMatLib;
        Width := Material.GetActualPrimaryTexture.Image.Width;
        Height := Material.GetActualPrimaryTexture.Image.Height;
        case i of
          1: Position.SetPoint(118, 240, 0);
          2: Position.SetPoint(320, 120, 0);
          3: Position.SetPoint(470, 290, 0);
        end;
        OverRadius := 40;
        OutRadius := 130;
        OnMouseOver := OnPlanetOver;
        OnMouseOut := OnPlanetOut;
      end;

      fGroup := TRadialGroup.CreateAsChild(fMainDummy);
        case i of
          1: fGroup.AddElements(['chat', 'gallery', 'chat']);
          2: fGroup.AddElements(['aside', 'audio', 'chat', 'default', 'chat']);
          3: fGroup.AddElements(['gallery', 'audio', 'default', 'chat']);
        end;
      fGroup.Position.SetPoint(fPlanet.Position.AsVector);
      fGroup.Material.MaterialLibrary := fMatLib;
      fGroup.OnMouseClick := OnItemMouseClick;
      if i = 2 then
        fGroup.GroupRadius := 90
      else
        fGroup.GroupRadius := 80;
    end;

  InitGlSceneProfiler(fMainDummy);    
end;

Procedure TfrmMain.InitMaterials;
begin
  AddMaterials(fMatLib, str_ImagesFolder + '\RadialGroup\', EarthMats, EarthMats);
  AddMaterials(fMatLib, str_ImagesFolder + '\RadialGroup\', PlanetMats, PlanetMats);
  AddMaterials(fMatLib, str_ImagesFolder + '\RadialGroup\', ['back_1'], ['back_1']);
end;

Procedure TfrmMain.InitTweener;
begin
  MousePressed := false;
  fTweener := TTweener.Create;
end;

Procedure TfrmMain.OnCadencerProgress(Sender : TObject; const deltaTime, newTime : Double);
var
  MPos: TPoint;
  i: integer;
begin
  fTweener.Update(DeltaTime);

  GetCursorPos(Mpos);
  MPos := fViewer.ScreenToClient(MPos);

  MousePressed := IsKeyDown(vk_LButton);
  for i := 1 to 3 do
    with fPlanets[i] do
    begin
      fGroup.SetMousePos(VectorMake(MPos.x, MPos.y, 0));
      fPlanet.SetMousePos(VectorMake(MPos.x, MPos.y, 0));
    end;
end;

end.

